/**
 * @author   Ivan Andonov
 * @email:   ivan.andonov[at]gmail[dot]com
 *
 * @require  init
 *           use  sjs.Debug
 * @optional     
 **/

(function() {
	
	var Class = {
		/*
		* Each new class(and its instances) has following:
		* 
		* Properties
		*   parent       : points to the object where the class is originaly created
		* 
		* Methods
		*   extend       : a way to add more functionality
		*   toString     : give the class path and its name
		*   instances    : return the count of the instances of the class 
		*   classInstance: return the class (only for instances)
		* 
		* If the new class has method initialize it will be used
		* for initialization of each instance of the class
		* 
		*/
		create : function(classPath, props, prv, rewrite) {
			if (!classPath) {
				this.log('classPath is missing');
			} else if (this.getClass(classPath) && !rewrite) {
				this.log(classPath+' already exists');
			} else {
				var classPath_arr = classPath.split('.');
				var className = classPath_arr.pop();
				var s_count = 0;
				var parent;
				if (classPath_arr.length) {
					parent = this.getClass(classPath_arr);
					// create the parent of the class is not existing
					if (!parent) {
						var path = '', tmp_className, tmp_class;
						while (classPath_arr.length) {
							tmp_className = classPath_arr.shift();
							if (path.length) {
								path += '.';
							}
							path += tmp_className;
							
							tmp_class = this.getClass(path);
							if (!tmp_class) {
								tmp_class = this.create(path);
							}
						}
						parent = tmp_class;
					}
				}
				parent = parent || window;
				
				function toString(name) {
					return (parent != window ? parent + '.' : '') + (name || className);
				};
				
				// create the class
				var cls = parent[className] = function () {
					
					// PRIVATE PROPS
					this.parent = cls.parent;
					
					// PUBLIC METHODS
					var instance_num = s_count++;
					this.toString = function() {
						return toString(className + instance_num);
					};
					this.classInstance = function() {
						return cls;
					};
					this.instances = function() {
						return cls.instances();
					};
					this.extend = cls.extend;
					
					// call constructor of the class
					if (cls.initialize) {
						try {
							cls.initialize.apply(this, arguments);
						} catch (error) {
							var e = error.description || error;
							Class.log(e);
						}
					}
					return this;
				};
				
				// STATIC PROPS
				cls.parent = parent;
				
				// STATIC METHODS
				cls.toString = toString;
				cls.extend = function(obj, rewrite) {
					for (var prop in obj) {
						if (rewrite || this[prop] === undefined) {
							this[prop] = obj[prop];
						} else {
							var e = 'WARNING: "'+prop+'" already exists!';
							this.log(e);
						}
					}
					return this;
				};
				cls.instances = function() {
					return s_count;
				};
				
				// add static props and methods or rewrite the predefined ones
				cls.extend(props, true);
				
				return cls;
			}
		},
		
		getClass : function(classPath) {
			var path_arr;
			if (String(typeof(classPath)).toLowerCase() == 'string') {
				path_arr = classPath.split('.');
			} else if (classPath.length) { // is array
				path_arr = classPath;
			} else {
				return false;
			}
			
			var parent = window;
			for (var i = 0, len = path_arr.length; i < len; i++) {
				parent = parent[path_arr[i]];
				if (!parent) {
					return false;
				}
			}
			return parent;
		},
		
		log : function(e, skipAlert) {
			if (window.sjs && window.sjs.Debug) {
				$logError(e);
			} else if (window.console) { // firebug
				window.console.log(e);
			} else if (!skipAlert){
				alert(e);
			}
		}
	};
	
	var userAgent = navigator.userAgent.toLowerCase();
	Class.create('sjs', {
	
		isPageLoaded : false,
		base : window.base || '',
		jsPath : window.jsPath || 'js/',
		cssPath : window.cssPath || 'css/',
		
		browser : {
			version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
			safari: /webkit/.test(userAgent),
			opera: /opera/.test(userAgent),
			msie: /msie/.test(userAgent) && !/opera/.test(userAgent),
			msie6: /msie 6/.test(userAgent) && !/opera/.test(userAgent),
			msie7: /msie 7/.test(userAgent) && !/opera/.test(userAgent),
			mozilla: /mozilla/i.test(userAgent) && !/(compatible|webkit)/.test(userAgent),
			firefox: /firefox/i.test(userAgent)
		},
		
		onLoad : function() {
			$log(this+'.onLoad');
			this.isPageLoaded = true;
		},
		
		create : function() {
			return Class.create.apply(Class, arguments)
		}
		
	});
	
})();